package com.huang.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huang.auth.constants.AuthConstants;
import com.huang.auth.constants.AuthorityWrapperConstant;
import com.huang.auth.constants.MenuWrapperConstant;
import com.huang.auth.converter.AuthMenuSimpleVOConverter;
import com.huang.auth.converter.AuthMenuVOConverter;
import com.huang.auth.converter.AuthResourcePOTOMenuSimpleVO;
import com.huang.auth.dao.AuthMenuDao;
import com.huang.auth.dao.AuthResourceDao;
import com.huang.auth.entity.po.AuthMenuPO;
import com.huang.auth.entity.po.AuthResourcePO;
import com.huang.auth.entity.request.AuthMenuAddRequest;
import com.huang.auth.entity.request.AuthMenuEditRequest;
import com.huang.auth.entity.vo.AuthMenuSimpleVO;
import com.huang.auth.entity.vo.AuthMenuVO;
import com.huang.auth.service.AuthMenuService;
import com.huang.utils.ObjectIdUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单(AuthMenu)表服务实现类
 *
 * @author HuangShen
 * @since 2021-09-21 17:13:47
 */
@Service("authMenuService")
@Slf4j
public class AuthMenuServiceImpl extends ServiceImpl<AuthMenuDao, AuthMenuPO> implements AuthMenuService {

    @Resource
    private AuthMenuDao authMenuDao;

    @Resource
    private AuthResourceDao authResourceDao;

    @Resource
    private AuthMenuSimpleVOConverter authMenuSimpleVOConverter;
    @Resource
    private AuthResourcePOTOMenuSimpleVO authResourcePOTOMenuSimpleVO;
    @Resource
    private AuthMenuVOConverter authMenuVOConverter;


    @Override
    @Transactional
    public boolean addMenu(AuthMenuAddRequest authMenuAddRequest) {
        AuthMenuPO authMenuPO = new AuthMenuPO();
        authMenuPO.setId(ObjectIdUtils.getInstance().nextId());
        authMenuPO.setName(authMenuAddRequest.getName());
        authMenuPO.setTitle(authMenuAddRequest.getTitle());
        authMenuPO.setDescribe(authMenuAddRequest.getDescribe());
        authMenuPO.setPublic(authMenuAddRequest.getIsPublic());
        authMenuPO.setPath(authMenuAddRequest.getPath());
        authMenuPO.setComponent(authMenuAddRequest.getComponent());
        authMenuPO.setDot(authMenuAddRequest.getDot());
        if (Objects.equals(authMenuAddRequest.getParentId(), AuthConstants.ROOT_MENU_ID)) {
            authMenuPO.setLevel(1);
        } else {
            AuthMenuPO parentMenu = this.authMenuDao.selectById(authMenuAddRequest.getParentId());
            authMenuPO.setLevel(parentMenu.getLevel() + 1);
        }
        authMenuPO.setSortValue(authMenuAddRequest.getSortValue());
        authMenuPO.setIcon(authMenuAddRequest.getIcon());
        authMenuPO.setBadge(authMenuAddRequest.getBadge());
        authMenuPO.setParentId(Long.valueOf(authMenuAddRequest.getParentId()));
        authMenuPO.setCreateUser(Long.valueOf(authMenuAddRequest.getCreateUser()));
        authMenuPO.setUpdateUser(Long.valueOf(authMenuAddRequest.getCreateUser()));
        // 创建菜单
        int insertMenu = authMenuDao.insert(authMenuPO);
        if (!CollectionUtils.isEmpty(authMenuAddRequest.getAuthResources())) {
            // 为菜单绑定资源
            List<Long> collect = authMenuAddRequest.getAuthResources().stream().map(Long::parseLong).collect(Collectors.toList());
            int insertResource = authResourceDao.updateMenuIdBatch(authMenuPO.getId(), collect);
            return insertMenu > 0 && insertResource > 0;
        }
        return insertMenu > 0;
    }

    @Override
    @Transactional
    public boolean editMenu(AuthMenuEditRequest authMenuEditRequest) {
        AuthMenuPO authMenuPO = new AuthMenuPO();
        String id = StringUtils.equals(authMenuEditRequest.getId(), "0") ? "0" : authMenuEditRequest.getId().substring(0, authMenuEditRequest.getId().indexOf("$"));
        authMenuPO.setId(Long.valueOf(id));
        authMenuPO.setName(authMenuEditRequest.getName());
        authMenuPO.setTitle(authMenuEditRequest.getTitle());
        authMenuPO.setDescribe(authMenuEditRequest.getDescribe());
        authMenuPO.setPublic(authMenuEditRequest.getIsPublic());
        authMenuPO.setPath(authMenuEditRequest.getPath());
        authMenuPO.setComponent(authMenuEditRequest.getComponent());
        authMenuPO.setDot(authMenuEditRequest.getDot());
        authMenuPO.setLevel(authMenuEditRequest.getLeve());
        authMenuPO.setSortValue(authMenuEditRequest.getSortValue());
        authMenuPO.setIcon(authMenuEditRequest.getIcon());
        authMenuPO.setBadge(authMenuEditRequest.getBadge());
        authMenuPO.setParentId(Long.valueOf(authMenuEditRequest.getParentId()));
        authMenuPO.setUpdateUser(Long.valueOf(authMenuEditRequest.getUpdateUser()));

        List<Long> reqResource = authMenuEditRequest.getAuthResources().stream().map(Long::parseLong).collect(Collectors.toList());
        // 更新菜单信息
        int menuEdit = authMenuDao.updateById(authMenuPO);


        QueryWrapper<AuthResourcePO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(AuthorityWrapperConstant.ID);
        queryWrapper.eq(AuthorityWrapperConstant.MENU_ID, authMenuPO.getId());
        // 1 查询目前菜单绑定的资源
        List<Long> authResourcePOIds = authResourceDao.selectList(queryWrapper).stream().map(AuthResourcePO::getId).collect(Collectors.toList());

        // 资源为null 清楚资源绑定的菜单
        if (CollectionUtils.isEmpty(reqResource)) {
            if (CollectionUtils.isEmpty(authResourcePOIds)){
                return menuEdit > 0;
            }
            return menuEdit > 0 && authResourceDao.updateMenuIdBatch(null, authResourcePOIds) > 0;
        }
        // 2  需移除的资源id
        List<Long> removeMenuIds = authResourcePOIds.stream().filter(aLong -> !reqResource.contains(aLong)).collect(Collectors.toList());
        // 3 新增的资源id
        List<Long> addMenuIds = reqResource.stream().filter(aLong -> !authResourcePOIds.contains(aLong)).collect(Collectors.toList());
        int updateResourceRes = 1;
        // menu Id 设置为null 则资源就想当于解绑
        if (!CollectionUtils.isEmpty(removeMenuIds)) {
            updateResourceRes = authResourceDao.updateMenuIdBatch(null, removeMenuIds);
        }
        if (!CollectionUtils.isEmpty(addMenuIds)) {
            // 给资源添加资源
            updateResourceRes = authResourceDao.updateMenuIdBatch(authMenuPO.getId(), addMenuIds);
        }
        return menuEdit > 0 && updateResourceRes > 0;

    }

    @Override
    public List<AuthMenuSimpleVO> menuSimpleListV1() {
        QueryWrapper<AuthMenuPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(MenuWrapperConstant.ID, MenuWrapperConstant.TITLE, MenuWrapperConstant.LEVEL, MenuWrapperConstant.PARENT_ID);
        List<AuthMenuPO> authMenuPOS = authMenuDao.selectList(queryWrapper);

        // 根据 菜单等级分组
        Map<Integer, List<AuthMenuPO>> authMenuGroupByLeve = authMenuPOS.stream().collect(Collectors.groupingBy(AuthMenuPO::getLevel));
        // 获取一级菜单
        List<AuthMenuSimpleVO> authMenuSimpleVOParents = authMenuSimpleVOConverter.batchConvert(authMenuGroupByLeve.get(1));
        // 获取二级菜单
        List<AuthMenuSimpleVO> authMenuSimpleVOChildren = authMenuSimpleVOConverter.batchConvert(authMenuGroupByLeve.get(2));
        // 二级菜单根据 父Id 分组
        Map<String, List<AuthMenuSimpleVO>> authMenuSimpleVOChildrenGroupByParentId = authMenuSimpleVOChildren.stream().collect(Collectors.groupingBy(AuthMenuSimpleVO::getParentId));
        // 为一级菜单设置二级菜单
        authMenuSimpleVOParents.forEach(authMenuSimpleVOParent -> {
            // 根据父id 找到 二级菜单
            List<AuthMenuSimpleVO> children = authMenuSimpleVOChildrenGroupByParentId.get(authMenuSimpleVOParent.getId());
            children.forEach(c -> {
                // 根据二级菜单id 查找菜单下的资源
                QueryWrapper<AuthResourcePO> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq(AuthorityWrapperConstant.MENU_ID, c.getId());
                List<AuthMenuSimpleVO> authMenuSimpleResourceVOS = authResourcePOTOMenuSimpleVO.batchConvert(this.authResourceDao.selectList(queryWrapper1));
                // 为二级菜单设置资源
                c.setChildren(authMenuSimpleResourceVOS);
            });
            authMenuSimpleVOParent.setChildren(children);
        });

        return authMenuSimpleVOParents;
    }

    /**
     * 获取简单菜单与操作点列表
     *
     * @return List<AuthMenuSimpleVO>
     */
    @Override
    public List<AuthMenuSimpleVO> menuSimpleListV2() {
        QueryWrapper<AuthMenuPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(MenuWrapperConstant.ID, MenuWrapperConstant.TITLE, MenuWrapperConstant.LEVEL, MenuWrapperConstant.PARENT_ID);
        List<AuthMenuPO> authMenuPOS = authMenuDao.selectList(queryWrapper);
        //
        List<AuthMenuSimpleVO> authMenuSimpleVOList = authMenuSimpleVOConverter.batchConvert(authMenuPOS);
        List<AuthMenuSimpleVO> authMenuSimpleVOTree = new ArrayList<>();
        authMenuSimpleVOList.forEach(authMenuSimpleVO -> {
            // 找到根结点  根结点的 ParentId为0
            if (StringUtils.equals(authMenuSimpleVO.getParentId(), AuthConstants.ROOT_MENU_ID)) {
                authMenuSimpleVOTree.add(authMenuSimpleVO);
            }
            // 找到当前节点的子节点
            List<AuthMenuSimpleVO> children = authMenuSimpleVOList.stream().filter(authMenuSimple -> StringUtils.equals(authMenuSimpleVO.getId(), authMenuSimple.getParentId())).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(children)) {
                // 没有子节点 查找操作点
                QueryWrapper<AuthResourcePO> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq(AuthorityWrapperConstant.MENU_ID, authMenuSimpleVO.getId());
                List<AuthMenuSimpleVO> authMenuSimpleResourceVOS = authResourcePOTOMenuSimpleVO.batchConvert(this.authResourceDao.selectList(queryWrapper1));
                authMenuSimpleVO.setChildren(authMenuSimpleResourceVOS);
                return;
            }
            authMenuSimpleVO.setChildren(children);

        });


        return authMenuSimpleVOTree;
    }

    @Override
    public List<AuthMenuVO> menuList(Long parentId) {
        if (Objects.isNull(parentId)) {
            return Collections.emptyList();
        }
        QueryWrapper<AuthMenuPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(MenuWrapperConstant.PARENT_ID, parentId);
        List<AuthMenuPO> authMenuPOS = this.authMenuDao.selectList(queryWrapper);
        return authMenuVOConverter.batchConvert(authMenuPOS);

    }

    @Override
    public List<List<String>> authorizedMenuAndIds(long roleId) {
        // 根据角色id 查处角色拥有的资源
        List<AuthResourcePO> authResourcePOByRoles = this.authResourceDao.getAuthResourceByRoleId(roleId);
        // 根据角色id 查找角色拥有的菜单
        List<AuthMenuPO> authMenuPOS = this.authMenuDao.getAuthMenuByRoleId(roleId);
        List<List<String>> menuIdss = new ArrayList<>();
        List<AuthMenuSimpleVO> authMenuSimpleVOList = authMenuSimpleVOConverter.batchConvert(authMenuPOS);
        List<AuthMenuSimpleVO> authMenuSimpleVOTree = new ArrayList<>();
        // 菜单转为树状
        authMenuSimpleVOList.forEach(authMenuSimpleVO -> {

            // 找到根结点  根结点的 ParentId为0
            if (StringUtils.equals(authMenuSimpleVO.getParentId(), AuthConstants.ROOT_MENU_ID)) {
                authMenuSimpleVOTree.add(authMenuSimpleVO);
            }
            // 找到当前节点的子节点
            List<AuthMenuSimpleVO> children = authMenuSimpleVOList.stream().filter(authMenuSimple -> StringUtils.equals(authMenuSimpleVO.getId(), authMenuSimple.getParentId())).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(children)) {
                // 没有子节点 查找操作点
                List<AuthResourcePO> resources = authResourcePOByRoles.stream()
                        .filter(authResourcePO -> StringUtils.equals(authResourcePO.getMenuId().toString(), authMenuSimpleVO.getId()))
                        .collect(Collectors.toList());
                List<AuthMenuSimpleVO> authMenuSimpleResourceVOS = authResourcePOTOMenuSimpleVO.batchConvert(resources);
                authMenuSimpleVO.setChildren(authMenuSimpleResourceVOS);
                return;
            }
            authMenuSimpleVO.setChildren(children);


        });
        // 遍历树状结构
        authMenuSimpleVOTree.forEach(authMenuSimpleNode -> {
            String path="";
            traverseTree(authMenuSimpleNode, menuIdss, path);
        });
        return menuIdss;
    }


    /**
     * 用于配合前段 级联选择框展示角色拥有的权限与菜单ID
     * @param node
     * @param menuIdss
     * @param path
     */
    public void traverseTree(AuthMenuSimpleVO node, List<List<String>> menuIdss, String path) {
        String finalPath;
        if (StringUtils.isEmpty(path)){
            finalPath = node.getId();
        }else {
            finalPath = path + "," + node.getId();
        }

        if (CollectionUtils.isEmpty(node.getChildren())) {
            List<String> authMenuResourceIds = Arrays.asList(finalPath.split(","));
            menuIdss.add(authMenuResourceIds);
            // 没有字节点返回
            return;
        }
        node.getChildren().forEach(children -> {
            traverseTree(children, menuIdss, finalPath);
        });
    }


}

